﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using WWLauncher.Constant;
using WWLauncher.ViewModel;

namespace WWLauncher.Util
{

    public class ProcessUtil
    {
        private static readonly AppConfig Config = MainViewModel.Instance().AppConfig;
        public ProcessUtil()
        {
        }
        public ProcessUtil(MainWindow mainWindow, AutoHidden autoHidden, bool isStartUp)
        {
            this.Window = mainWindow;
            this.AutoHidden = autoHidden;
            IsStartUp = isStartUp;
        }

        public AutoHidden AutoHidden { get; set; }
        public MainWindow Window { get; set; }
        private bool IsStartUp = false;
        public ProcessEnum StartIconApp(IconInfo icon, bool useRelativePath = false, bool isAdminStartUp = false)
        {
            try
            {
                var pp = ProcessEnum.Success;

                if (IsStartUp)
                {
                    var fileName = Path.GetFileNameWithoutExtension(icon.TargetPath);
                    var process = Process.GetProcessesByName(fileName).FirstOrDefault();
                    if (process != null)
                    {
                        return ProcessEnum.Success;
                    }
                }

                if (icon.StartType == IconStartType.ShowInExplore)
                {
                    return ShowInExplore(icon);
                }
                using (var p = new Process())
                {
                    string startArg = icon.StartArg;
                    if (startArg != null && Constants.SystemIcons.ContainsKey(startArg))
                    {
                        pp = StartSystemApp(icon, isAdminStartUp);
                    }
                    else
                    {
                        string path;
                        if (useRelativePath)
                        {
                            string fullPath = Path.Combine(Constants.AppDir, icon.RelativePath);
                            path = Path.GetFullPath(fullPath);
                        }
                        else
                        {
                            path = icon.TargetPath;
                        }
                        p.StartInfo.FileName = path;
                        if (!startArg.IsNullOrEmpty())
                        {
                            p.StartInfo.Arguments = startArg;
                        }

                        if (path.IndexOf("\\") >= 0)
                            p.StartInfo.WorkingDirectory = path.Substring(0, path.LastIndexOf("\\"));

                        var startType = icon.StartType;
                        if (isAdminStartUp)
                        {
                            startType = IconStartType.AdminStartUp;
                        }

                        switch (startType)
                        {
                            case IconStartType.AdminStartUp:
                                p.StartInfo.Verb = "runas";
                                p.StartInfo.UseShellExecute = true;
                                break;
                            case IconStartType.DefaultStartup:
                                break;
                            case IconStartType.ShowInExplore:
                                p.StartInfo.FileName = "Explorer.exe";
                                p.StartInfo.Arguments = "/e,/select," + icon.TargetPath;
                                break;
                            case IconStartType.OpenWithBrowser:
                                p.StartInfo.FileName = "cmd";
                                p.StartInfo.Arguments = "/c start " + icon.TargetPath;
                                break;

                        }

                        if ((icon.StartType is IconStartType.AdminStartUp or IconStartType.DefaultStartup)
                            && !File.Exists(path) && !Directory.Exists(path))
                        {
                            //如果没有使用相对路径  那么使用相对路径启动一次
                            if (!useRelativePath)
                            {
                                pp = StartIconApp(icon, true);
                                return pp;
                            }
                            else
                            {
                                return ProcessEnum.FileNotFound;
                            }
                        }
                        //(关系表达式) ? 表达式1 : 表达式2;
                        pp = p.Start() ? ProcessEnum.Success : ProcessEnum.OtherErrors;

                        //启动链接应用
                        if (icon.LinkId != Guid.Empty)
                        {
                            IconInfo linkIco = null;
                            MainViewModel.Instance().AllIcons().ForEach(item =>
                            {
                                if (icon.LinkId == item.Id)
                                {
                                    linkIco = item;
                                    return;
                                }
                            });

                            if (linkIco != null)
                            {
                                var fileName = Path.GetFileNameWithoutExtension(linkIco.TargetPath);
                                var process = Process.GetProcessesByName(fileName).FirstOrDefault();
                                if (process == null)
                                {
                                    Process.Start(linkIco.TargetPath, linkIco.StartArg);
                                }
                            }
                        }
                        Window.Extend();

                        Action(pp);

                        if (useRelativePath)
                        {
                            //如果使用相对路径启动成功 那么重新设置程序绝对路径
                            icon.TargetPath = path;
                        }

                    }
                }
                icon.Count++;
                ConfigUtil.SaveAppData();

                //隐藏搜索框
                if (RunTimeStatus.SearchBoxShow)
                {
                    Window.HidedSearchBox();
                }
                return pp;
            }
            catch (PlatformNotSupportedException ex)
            {

                LogUtil.WriteErrorLog(ex, "程序启动失败:TargetPath=" + icon.TargetPath + ",StartType=" + icon.StartType + "," + ex.Message);
                return ProcessEnum.PlatformNotSupportedException;
            }
            catch (System.ComponentModel.Win32Exception ex)
            {

                LogUtil.WriteErrorLog(ex, "程序启动失败:TargetPath=" + icon.TargetPath + ",StartType=" + icon.StartType + "," + ex.Message);
                return ProcessEnum.Win32Exception;
            }
            catch (Exception)
            {
                if (!useRelativePath)
                {
                    return StartIconApp(icon, true);
                }

                return ProcessEnum.OtherErrors;
            }
        }

        public ProcessEnum ShowInExplore(IconInfo icon)
        {
            var pp = ProcessEnum.Success;
            using (var p = new Process())
            {
                p.StartInfo.FileName = "Explorer.exe";
                p.StartInfo.Arguments = "/e,/select," + icon.TargetPath;

                pp = p.Start() ? ProcessEnum.Success : ProcessEnum.OtherErrors;

                Action(pp);

            }
            icon.Count++;

            ConfigUtil.SaveAppData();
            return pp;
        }
        private void Action(ProcessEnum pp)
        {
            if (pp == ProcessEnum.Success && Config.AppHideType == AppHideType.StartExe && !RunTimeStatus.LockAppPanel)
            {
                //如果开启了贴边隐藏 则窗体不贴边才隐藏窗口
                if (Config.MarginHide)
                {
                    if (!AutoHidden.IsMargin() && !MouseUtil.MouseInWindow(Window))
                    {
                        Window.HideApp();
                    }
                    else
                    {
                        WaitHide(4000, () =>
                        {
                            Window.HideApp();
                        });
                    }
                }
                else
                {
                    Window.HideApp();
                }
            }
        }
        public void WaitHide(int waitTime, Action value)
        {
            Thread t = new Thread(() =>
            {
                Thread.Sleep(waitTime);
                Window.Dispatcher.BeginInvoke(() =>
                {
                    if (value != null)
                        value.Invoke();
                });
            })
            {
                IsBackground = true
            };
            t.Start();
        }
        private ProcessEnum StartSystemApp(IconInfo info, bool isAdminStartUp = false)
        {
            string startArg = info.StartArg;
            if (info.StartType == IconStartType.ShowInExplore)
            {
                return ProcessEnum.FileNotFound;
            }
            if (info.StartType == IconStartType.AdminStartUp)
            {
                isAdminStartUp = true;
            }
            switch (startArg)
            {
                case "Calculator":
                    Process.Start("calc.exe");
                    break;
                case "Computer":
                    Process.Start("explorer.exe");
                    break;
                case "GroupPolicy":
                    Process.Start("gpedit.msc");
                    break;
                case "Notepad":
                    Process.Start("notepad");
                    break;
                case "Network":
                    Process.Start("ncpa.cpl");
                    break;
                case "RecycleBin":
                    Process.Start("shell:RecycleBinFolder");
                    break;
                case "Registry":
                    Process.Start("regedit.exe");
                    break;
                case "Mstsc":
                    if (isAdminStartUp)
                    {
                        Process.Start("mstsc", "-admin");
                    }
                    else
                    {
                        Process.Start("mstsc");
                    }
                    break;
                case "Control":
                    Process.Start("Control");
                    break;
                case "CMD":
                    if (isAdminStartUp)
                    {
                        using (Process process = new Process())
                        {
                            process.StartInfo.FileName = "cmd.exe";
                            process.StartInfo.Verb = "runas";
                            process.Start();
                        }
                    }
                    else
                    {
                        Process.Start("cmd");
                    }
                    break;
                case "Services":
                    Process.Start("services.msc");
                    break;
            }
            //如果开启了贴边隐藏 则窗体不贴边才隐藏窗口
            if (Config.MarginHide)
            {
                if (!AutoHidden.IsHide)
                {
                    Window.HideApp();
                }
            }
            else
            {
                Window.HideApp();
            }
            return ProcessEnum.Success;
        }

    }
    public enum ProcessEnum
    {
        [Description("成功")]
        Success = 0,
        [Description("平台不支持")]
        PlatformNotSupportedException,
        [Description("可能需要管理员权限")]
        Win32Exception,
        [Description("系统项目不支持打开文件位置操作")]
        FileNotFound,
        [Description("其他异常")]
        OtherErrors

    }
}
